package com.lnsoft.cac.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.ResourceLeakDetector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class CACServer {

    private static final Logger logger = LoggerFactory.getLogger(CACServer.class);

    @Value("${netty.server.so_backlog}")
    private int soBackLog;
    @Value("${netty.server.port}")
    private int port;

    @Value("${project.is_test}")
    private boolean isTest;


    @Autowired
    private CACChannelInitializer CACChannelInitializer;

    private Channel channel;
    private EventLoopGroup bossGroup;
    private EventLoopGroup workGroup;


    //@PostConstruct 构造方法执行之后，会调用这个注解的方法 =>sevelet构造方法之后，init方法之前
    public void start() throws InterruptedException {


        // netty 提供的坚持内存泄露信息 ADVANCED启动
        ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);


        // 处理客户端请求连接事件
        bossGroup = new NioEventLoopGroup(1);
        // 处理已连接的客户端的触发事件  优化点： 2的指数
        workGroup = new NioEventLoopGroup(8);

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, soBackLog)
                    .option(ChannelOption.SO_RCVBUF, 1600) // 缓冲区大小 大气腐蚀终端交互数据包最大值为256
                    .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) // 缓冲区池化操作
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(CACChannelInitializer);
            logger.debug("server port : " + port);
            ChannelFuture channelFuture = bootstrap.bind(port).sync();
            if(isTest){
                // 测试环境下使用
                bootstrap.bind(2500).sync();
                bootstrap.bind(2501).sync();
                bootstrap.bind(2502).sync();
                bootstrap.bind(2503).sync();
                bootstrap.bind(2505).sync();
                bootstrap.bind(2506).sync();
                bootstrap.bind(2507).sync();
                bootstrap.bind(2508).sync();
                bootstrap.bind(2509).sync();
                bootstrap.bind(2510).sync();
                for(int i = 2511 ; i<2561; i++){
                    bootstrap.bind(i).sync();
                }
            }


            channel =  channelFuture.channel();

           // channel.closeFuture().sync();
        } finally {
            // 优雅关闭
//            logger.info("netty 优雅关闭");
//            workGroup.shutdownGracefully();
//            bossGroup.shutdownGracefully();
        }

    }


    //@PreDestroy (servlet destory方法执行之后)
    public void stop(){
        try{
            channel.close().sync();
        }catch (Exception e){

        }finally {
            logger.info("netty 优雅关闭");
            workGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }

    }

}
